package article8.finalizer.cleaner;

import sun.misc.Cleaner;

/**
 * 第8条：避免使用终结方法和清除方法
 * 终结方法（finalizer）通常是不可预测的，也是很危险的，一般情况下是不必要的.用终结方法会导致行为不稳定 性能降低，以及可移植性问题
 * 清除方法（cleaner）代替了终结方法.清除方法没有终结方法那么危险，但仍然是不可预测、运行缓慢，一般情况下也是不必要的.
 * 少数情况会出现延迟终结甚至根本不执行终结方法
 * Java 语言规范不仅不保证终结方法或者清除方法会被及时地执行，而且根本就不保证它们会被执行。
 * 结论：永远不应该依赖终结方法或者清除方法来更新重要的持久状态
 *
 * 如果异常发生在终结方法之中，则不会如此，甚至连警告都不会打印出来 清除方法没有这个问题，
 * 因为使用清除方法的一个类库在控制它的线程
 * 使用终结方法和清除方法有一个非常严重的性能损失。
 *
 * 终结方法有一个严重的安全问题：它们为终结方法攻击（ finalizer attack 打开了类的大门，终结方法攻击背后的思想很简单：如果从构造器或者它的序列化对
 * 等体（readObject和readResolve方法，详见12章）抛出异常，恶意子类的终结方法就可以构造了一部分的应该已经半途夭折的对象上运行。这个终结方法会将对
 * 该对象的引用记录在一个静态域中，组织它被垃圾回收。一旦记录到异常的对象，就可以轻松地在这个对象上调用任何原本永远不允许在这里出现的方法
 * 从构造器抛出的异常，应该足以防止对象继续存在；有了终结方法的存在，这一点就做不到了。这种攻击可能造成致命的后果 final类不会受到终
 * 结方法攻击，因为没有人能够编写出 final 类的恶意子类。为了防止非 final 类受到终结方法攻击 要编写一个空的final的finalize方法
 *
 * 那么，如果类的对象中封装的资源（例如文件或者线程）确实需要终止，应该怎么做才能不用编写终结方法或者清除方法呢？
 * 只需 让类实现 AutoCloseable ，并要求其客户端在每个实例不再需要的时候调用 close 方法，
 * 一般是利用 try-with-resources 确保终止，即使遇到异常也是如此（详见第9条）
 *
 * 【该类要求jdk9】
 * 这项有点懵 回头需要温习
 * @Author: cctv
 * @Date: 2019/3/28 10:49
 */
public class Room implements AutoCloseable {
//    private static final Cleaner cleaner = Cleaner.create();


    /**
     * Resource that requires cleaning. Must nit refer to Room!
     */
    private static class State implements Runnable {

        /**
         * Number of junk poles in this room
         */
        int numJunkPiles;

        State(int numJunkPiles){
            this.numJunkPiles = numJunkPiles;
        }

        @Override
        public void run() {
            System.out.println("Cleaning room");
            numJunkPiles=0;
        }
    }

    /**
     * The state of this room, shared with our cleanable
     */
    private final State state;
    /**
     * Our cleanable. Cleans the room when it’s eligible for gc
     */
//    private final Cleaner.Cleanable cleanable;

    public Room(int numJunkPiles) {
        state = new State(numJunkPiles);
//        cleanable = cleaner.register(this, state);
    }

    @Override
    public void close() {
//        cleanable.clean();
    }


}
